const JSSHA = require('jssha')
const base32Decode = require('base32-decode')
const db = require('../models/db')

// 存储当前活跃的TOTP验证码
let totpCodesCache = {}
// 存储TOTP账户信息
const totpAccountsMap = {}

// 生成TOTP验证码
const generateTOTPCode = (secret) => {
  try {
    // 移除空格和换行符
    const sanitizedSecret = secret.replace(/\s/g, '').toUpperCase()

    // 解码Base32
    const decoded = base32Decode(sanitizedSecret, 'RFC4648')

    // 计算当前时间戳
    const epoch = Math.floor(Date.now() / 1000)
    let timeCounter = Math.floor(epoch / 30)

    // 转换为字节数组
    const timeByteArray = new Uint8Array(8)
    for (let i = 0; i < 8; i++) {
      timeByteArray[7 - i] = timeCounter & 0xff
      timeCounter = timeCounter >> 8
    }

    // 使用HMAC-SHA1计算哈希
    const shaObj = new JSSHA('SHA-1', 'ARRAYBUFFER')
    shaObj.setHMACKey(decoded, 'ARRAYBUFFER')
    shaObj.update(timeByteArray.buffer)
    const hmac = shaObj.getHMAC('ARRAYBUFFER')

    // 根据RFC获取截断索引
    const offset = new Uint8Array(hmac)[19] & 0xf

    // 从哈希中提取4字节
    const bytes = new Uint8Array(hmac)
    const binary =
      ((bytes[offset] & 0x7f) << 24) |
      ((bytes[offset + 1] & 0xff) << 16) |
      ((bytes[offset + 2] & 0xff) << 8) |
      (bytes[offset + 3] & 0xff)

    // 获取6位数字的TOTP码
    const otp = binary % 1000000

    // 确保是6位数字（前导零）
    return otp.toString().padStart(6, '0')
  } catch (error) {
    console.error('生成TOTP码失败:', error)
    return null
  }
}

// 保存验证码到数据库
const saveTOTPCodesToDB = async (codes, timestamp) => {
  try {
    // 将验证码和时间戳存储到数据库
    await db.totpCodes.bulkSave(
      Object.entries(codes).map(([accountId, code]) => ({
        accountId,
        code,
        timestamp,
        expiresAt: timestamp + 30 // 30秒后过期
      }))
    )
    return true
  } catch (error) {
    console.error('保存TOTP码到数据库失败:', error)
    return false
  }
}

// 从数据库获取验证码
const getTOTPCodesFromDB = async (accountIds) => {
  try {
    // 查询当前有效的验证码
    const currentTime = Math.floor(Date.now() / 1000)
    const storedCodes = await db.totpCodes.find({
      accountId: { $in: accountIds },
      expiresAt: { $gt: currentTime }
    })

    if (storedCodes && storedCodes.length > 0) {
      const codes = {}
      storedCodes.forEach((item) => {
        codes[item.accountId] = item.code
      })
      return codes
    }
    return null
  } catch (error) {
    console.error('从数据库获取TOTP码失败:', error)
    return null
  }
}

// 生成新的TOTP验证码
exports.generateTOTP = async (req, res) => {
  try {
    const { accountIds, newAccount } = req.body

    if (!accountIds || !Array.isArray(accountIds)) {
      return res.status(400).json({ error: '需要提供账户ID数组' })
    }

    // 如果提供了新账户信息，保存到映射中
    if (newAccount) {
      totpAccountsMap[newAccount.id] = newAccount
    }

    const codes = {}
    const timestamp = Math.floor(Date.now() / 1000)

    // 为每个账户生成验证码
    for (const accountId of accountIds) {
      const account = totpAccountsMap[accountId]
      if (account && account.secret) {
        const code = generateTOTPCode(account.secret)
        if (code) {
          codes[accountId] = code
        } else {
          codes[accountId] = '错误'
        }
      } else {
        codes[accountId] = '账户不存在'
      }
    }

    // 更新缓存
    totpCodesCache = {
      ...totpCodesCache,
      ...codes
    }

    // 保存到数据库
    await saveTOTPCodesToDB(codes, timestamp)

    return res.json({
      success: true,
      data: {
        codes,
        timestamp,
        expiresAt: timestamp + 30
      }
    })
  } catch (error) {
    console.error('生成TOTP验证码失败:', error)
    return res.status(500).json({ error: '生成验证码失败' })
  }
}

// 获取当前TOTP验证码
exports.getCurrentTOTP = async (req, res) => {
  try {
    const { accountId } = req.query

    if (!accountId) {
      return res.status(400).json({ error: '需要提供账户ID' })
    }

    // 检查缓存中是否有该账户的验证码
    if (totpCodesCache[accountId]) {
      return res.json({
        success: true,
        data: {
          code: totpCodesCache[accountId]
        }
      })
    }

    // 从数据库查询
    const codes = await getTOTPCodesFromDB([accountId])
    if (codes && codes[accountId]) {
      return res.json({
        success: true,
        data: {
          code: codes[accountId]
        }
      })
    }

    // 如果没有找到，生成新的验证码
    const account = totpAccountsMap[accountId]
    if (account && account.secret) {
      const code = generateTOTPCode(account.secret)
      if (code) {
        totpCodesCache[accountId] = code
        await saveTOTPCodesToDB({ [accountId]: code }, Math.floor(Date.now() / 1000))

        return res.json({
          success: true,
          data: {
            code
          }
        })
      }
    }

    return res.status(404).json({ error: '未找到有效的验证码' })
  } catch (error) {
    console.error('获取当前TOTP验证码失败:', error)
    return res.status(500).json({ error: '获取验证码失败' })
  }
}

// 批量获取TOTP验证码
exports.getBatchTOTP = async (req, res) => {
  try {
    const { accountIds } = req.body

    if (!accountIds || !Array.isArray(accountIds)) {
      return res.status(400).json({ error: '需要提供账户ID数组' })
    }

    // 先从数据库获取
    const dbCodes = await getTOTPCodesFromDB(accountIds)
    let codes = dbCodes || {}

    // 处理缺失的验证码
    const missingAccountIds = accountIds.filter((id) => !codes[id])

    if (missingAccountIds.length > 0) {
      // 为缺失的账户生成新验证码
      const newCodes = {}
      const timestamp = Math.floor(Date.now() / 1000)

      for (const accountId of missingAccountIds) {
        const account = totpAccountsMap[accountId]
        if (account && account.secret) {
          const code = generateTOTPCode(account.secret)
          if (code) {
            newCodes[accountId] = code
          } else {
            newCodes[accountId] = '错误'
          }
        } else {
          newCodes[accountId] = '账户不存在'
        }
      }

      // 更新缓存和数据库
      if (Object.keys(newCodes).length > 0) {
        totpCodesCache = {
          ...totpCodesCache,
          ...newCodes
        }

        await saveTOTPCodesToDB(newCodes, timestamp)

        // 合并结果
        codes = {
          ...codes,
          ...newCodes
        }
      }
    }

    return res.json({
      success: true,
      data: {
        codes
      }
    })
  } catch (error) {
    console.error('批量获取TOTP验证码失败:', error)
    return res.status(500).json({ error: '批量获取验证码失败' })
  }
}

// 同步账户信息
exports.syncAccounts = async (req, res) => {
  try {
    const { accounts } = req.body

    if (!accounts || !Array.isArray(accounts)) {
      return res.status(400).json({ error: '需要提供账户数组' })
    }

    // 更新账户映射
    accounts.forEach((account) => {
      totpAccountsMap[account.id] = account
    })

    // 将账户信息保存到数据库
    try {
      await db.totpAccounts.bulkSave(
        accounts.map((account) => ({
          id: account.id,
          name: account.name,
          secret: account.secret,
          issuer: account.issuer,
          userId: req.user?.id // 如果有用户认证系统
        }))
      )
    } catch (dbError) {
      console.error('保存账户信息到数据库失败:', dbError)
      // 继续执行，因为内存中已更新
    }

    return res.json({
      success: true,
      message: '账户同步成功'
    })
  } catch (error) {
    console.error('同步账户信息失败:', error)
    return res.status(500).json({ error: '同步账户信息失败' })
  }
}
